package com.wcs.exam.controller.biz;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.wcs.exam.common.base.BaseBiz;
import com.wcs.exam.common.constant.BaseConstant;
import com.wcs.exam.common.enums.QuestionTypeEnum;
import com.wcs.exam.common.util.BeanUtil;
import com.wcs.exam.controller.biz.resp.QuestionDetailResp;
import com.wcs.exam.dao.PaperQuestionDao;
import com.wcs.exam.dao.QuestionDao;
import com.wcs.exam.dao.QuestionOptionDao;
import com.wcs.exam.dao.impl.mapper.entity.PaperQuestion;
import com.wcs.exam.dao.impl.mapper.entity.Question;
import com.wcs.exam.dao.impl.mapper.entity.QuestionOption;
import com.wcs.exam.dao.po.PaperQuestionCiteCountPO;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Component
@RequiredArgsConstructor
public class QuestionCommonBiz extends BaseBiz {

    @NotNull
    private final QuestionDao dao;
    @NotNull
    private final QuestionOptionDao questionOptionDao;
    @NotNull
    private final PaperQuestionDao paperQuestionDao;

    /**
     * 获取题目详情
     *
     * @param id 题目ID
     * @return 题目详情
     */
    public QuestionDetailResp getDetailById(Long id) {
        Question question = dao.getById(id);
        if (ObjectUtil.isNull(question)) {
            return null;
        }

        QuestionDetailResp resp = BeanUtil.copyProperties(question, QuestionDetailResp.class);
        resp.setOptionCount(0);
        resp.setOptions(Collections.emptyList());
        resp.setQuestionAnswerIds(Collections.emptyList());

        if (QuestionTypeEnum.isExistOption(resp.getQuestionType())) {
            // 存在选项题目
            List<QuestionOption> optionList = questionOptionDao.listByQuestionId(resp.getId());
            resp.setOptions(BeanUtil.copyProperties(optionList, QuestionDetailResp.Option.class));

            // 获取题目答案ID
            List<Long> questionAnswerIds = getQuestionAnswerIds(resp.getQuestionAnswer(), optionList);
            resp.setQuestionAnswerIds(questionAnswerIds);
        } else if (QuestionTypeEnum.GAP_FILLING.getCode().equals(resp.getQuestionType())) {
            // 填空题
            int count = StrUtil.isNotBlank(resp.getQuestionAnswer()) ? resp.getQuestionAnswer().split(BaseConstant.GET_SEPARATOR).length : 0;
            resp.setOptionCount(count);
        }
        return resp;
    }

    /**
     * 根据题目ID获取题目详情
     *
     * @param ids 题目ID
     * @return 题目详情
     */
    public List<QuestionDetailResp> listDetailByIds(Collection<Long> ids) {
        // 获取题目
        List<Question> questionList = dao.listByIds(ids);
        if (CollectionUtil.isEmpty(questionList)) {
            return Collections.emptyList();
        }
        Set<Long> optionQuestionIds = new HashSet<>();
        // 题目ID，用于获取题目选项
        questionList.stream()
                .filter(item -> QuestionTypeEnum.isExistOption(item.getQuestionType()))
                .forEach(item -> optionQuestionIds.add(item.getId()));

        Map<Long, List<QuestionOption>> optionMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(optionQuestionIds)) {
            List<QuestionOption> optionList = questionOptionDao.listByQuestionIds(optionQuestionIds);
            if (CollectionUtil.isNotEmpty(optionList)) {
                optionMap.putAll(optionList.stream().collect(Collectors.groupingBy(QuestionOption::getQuestionId)));
            }
        }

        List<QuestionDetailResp> respList = BeanUtil.copyProperties(questionList, QuestionDetailResp.class);
        for (QuestionDetailResp resp : respList) {
            resp.setOptionCount(0);
            resp.setOptions(Collections.emptyList());
            resp.setQuestionAnswerIds(Collections.emptyList());

            if (QuestionTypeEnum.isExistOption(resp.getQuestionType())) {
                // 存在选项的题型
                List<QuestionOption> optionList = optionMap.get(resp.getId());
                if (CollectionUtil.isNotEmpty(optionList)) {
                    resp.setOptions(BeanUtil.copyProperties(optionList, QuestionDetailResp.Option.class));
                }

                // 获取题目答案ID
                List<Long> questionAnswerIds = getQuestionAnswerIds(resp.getQuestionAnswer(), optionList);
                resp.setQuestionAnswerIds(questionAnswerIds);
            } else if (QuestionTypeEnum.GAP_FILLING.getCode().equals(resp.getQuestionType())) {
                // 填空题
                int count = StrUtil.isNotBlank(resp.getQuestionAnswer()) ? resp.getQuestionAnswer().split(BaseConstant.GET_SEPARATOR).length : 0;
                resp.setOptionCount(count);
            }
        }

        return respList;
    }

    /**
     * 获取题目答案ID
     *
     * @param questionAnswer     题目答案
     * @param questionOptionList 选项信息
     * @return 试题答案ID
     */
    private List<Long> getQuestionAnswerIds(String questionAnswer, List<QuestionOption> questionOptionList) {
        if (StrUtil.isNotBlank(questionAnswer) && CollectionUtil.isNotEmpty(questionOptionList)) {
            // 判断选项是否是正确答案
            List<String> answerList = CollUtil.newArrayList(questionAnswer.split(BaseConstant.GET_SEPARATOR));

            List<Long> questionAnswerIds = new ArrayList<>();
            questionOptionList.forEach(option -> {
                if (answerList.contains(option.getOptionContent())) {
                    questionAnswerIds.add(option.getId());
                }
            });
            return questionAnswerIds;
        }
        return Collections.emptyList();
    }


    /**
     * 获取试题被引用状态
     *
     * @param questionIds 题目信息
     * @return 试题被引用状态
     */
    public Map<Long, Boolean> getQuestionCiteStatus(Collection<Long> questionIds) {
        if (CollectionUtil.isEmpty(questionIds)) {
            return Collections.emptyMap();
        }

        Map<Long, Boolean> citeMap = new HashMap<>();

        // 处理被试卷引用
        List<PaperQuestionCiteCountPO> paperQuestionCiteCountList = paperQuestionDao.questionCiteCunt(questionIds);
        if (CollectionUtil.isNotEmpty(paperQuestionCiteCountList)) {
            paperQuestionCiteCountList.forEach(item -> citeMap.put(item.getQuestionId(), item.getCount() > 0));
        }

        // 处理未被引用数据
        for (Long questionId : questionIds) {
            if (citeMap.containsKey(questionId)) {
                continue;
            }
            citeMap.put(questionId, Boolean.FALSE);
        }
        return citeMap;
    }

    /**
     * 试题被引用检查
     *
     * @param questionId 试题ID
     * @return 检查结果(false ： 未被引用 、 true ： 被引用)
     */
    public Boolean citeCheck(Long questionId) {
        // 校验是否被考试引用
        boolean paperCite = paperQuestionDao.lambdaQuery().eq(PaperQuestion::getQuestionId, questionId).exists();
        if (paperCite) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }
}
